﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Data.SqlClient;
using System.Linq;


namespace RISMOTAXDP.EmailService
{
    /// <summary>
    /// 全局对象
    /// </summary>
    public static class GlobalObject
    {
        #region 常量
        /// <summary>
        /// 发送标志_自动发送
        /// </summary>
        public const string FLAG_SEND_AUTO = "1";
        /// <summary>
        /// 发送标志_手动发送
        /// </summary>
        public const string FLAG_SEND_MANUAL = "2";
        /// <summary>
        /// 日期格式化字符串
        /// </summary>
        private const string FORMAT_DATE = "yyyyMMdd";
        /// <summary>
        /// 月份格式化字符串
        /// </summary>
        private const string FORMAT_MONTH = "yyyyMM";
        /// <summary>
        /// 日期格式化字符串（短）
        /// </summary>
        private const string FORMAT_SHORT_DATETIME = "yyyy-MM-dd";
        /// <summary>
        /// 日期格式化字符串（短）
        /// </summary>
        private const string FORMAT_LONG_DATETIME = "yyyy-MM-dd HH:mm:ss";
        /// <summary>
        /// 时间格式化字符串
        /// </summary>
        private const string FORMAT_TIME = "HHmmssfff";

        /// <summary>
        /// 邮件模板目录名称
        /// </summary>
        public const string MailTemplatesFolder = "MailTemplates";

        #endregion




        /// <summary>
        /// 系统信息
        /// </summary>
        public static SystemInfo SystemInfo;

        /// <summary>
        /// 数据库信息
        /// </summary>
        public static DataBaseInfo DataBaseInfo;

        /// <summary>
        /// 服务运行状态
        /// </summary>
        public static ServiceState State;

        /// <summary>
        /// 服务器日志路径
        /// </summary>
        public static string LogFilePath;

        /// <summary>
        /// 错误信息一览
        /// </summary>
        public static Dictionary<string, string> MSGResources;

        /// <summary>
        /// 邮件模板路径
        /// </summary>
        public static string MailTemplatePath;

        /// <summary>
        /// 全局对象初始化
        /// </summary>
        public static void Initialize()
        {
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
            string localPath = new System.IO.FileInfo(new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath).DirectoryName;
            GlobalObject.LogFilePath = System.IO.Path.Combine(localPath, "Log");
            GlobalObject.MailTemplatePath = System.IO.Path.Combine(localPath, MailTemplatesFolder);
            GlobalObject.SystemInfo = new SystemInfo();
            GlobalObject.DataBaseInfo = new DataBaseInfo();
            GlobalObject.State = ServiceState.Running;
            MSGResources = new Dictionary<string, string>();
            using (System.Resources.ResXResourceReader reader = new System.Resources.ResXResourceReader(System.IO.Path.Combine(localPath, "MsgResource.Resx")))
            {
                System.Collections.IDictionaryEnumerator dEnum = reader.GetEnumerator();
                while (dEnum.MoveNext())
                {
                    MSGResources.Add(dEnum.Key.ToString(), dEnum.Value.ToString());
                }
            }

            if (!Directory.Exists(LogFilePath)) Directory.CreateDirectory(LogFilePath);
        }

        /// <summary>
        /// 全局对象再初始化
        /// </summary>
        public static void ReInitialize()
        {
            GlobalObject.DataBaseInfo.ReInitialize();
            GlobalObject.SystemInfo.ReInitialize();
        }

        /// <summary>
        /// 捕获并记录应用程序域产生的错误异常信息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            Exception ex = (Exception)e.ExceptionObject;
            GlobalObject.WriteOperationLog("E80010000", ex);
            if (e.IsTerminating)
            {
                GlobalObject.WriteSystemLog("S00000002", null);
            }
        }

        /// <summary>
        /// 创建数据库连接
        /// </summary>
        /// <returns>返回数据库连接</returns>
        public static SqlConnection CreateConnect()
        {
            try
            {
                SqlConnection conn = new SqlConnection(SystemInfo.DBConnectString);
                conn.Open();
                return conn;
            }
            catch (Exception ex)
            {
                GlobalObject.WriteOperationLog("E80010001", ex);
                return null;
            }
        }

        /// <summary>
        /// 关闭数据库连接
        /// </summary>
        /// <param name="conn">数据库连接</param>
        public static void CloseConnect(SqlConnection conn)
        {
            try
            {
                if (conn != null && conn.State != System.Data.ConnectionState.Closed)
                {
                    conn.Close();
                }
            }
            catch (Exception ex)
            {
                GlobalObject.WriteOperationLog("E80010002", ex);
            }
        }

        /// <summary>
        /// 获取业务区分的邮件发送方式
        /// </summary>
        /// <param name="mailOpIndex"></param>
        /// <returns></returns>
        public static bool GetMailSendType(int mailOpIndex)
        {
            return DataBaseInfo.MailSendType == FLAG_SEND_AUTO;
        }

        /// <summary>
        /// 记录系统日志
        /// </summary>
        /// <param name="msgId">消息编号</param>
        /// <param name="ex">异常信息</param>
        /// <param name="paras">消息参数</param>
        public static void WriteSystemLog(string msgId, Exception ex, params object[] paras)
        {
            WriteLog(GetSystemLogPath(), string.Format(msgId + " " + MSGResources[msgId], paras), ex);
        }

        /// <summary>
        /// 记录操作日志
        /// </summary>
        /// <param name="msgId">消息编号</param>
        /// <param name="ex">异常信息</param>
        /// <param name="paras">消息参数</param>
        public static void WriteOperationLog(string msgId, Exception ex, params object[] paras)
        {
            WriteLog(GetOperationLogPath(), string.Format(msgId + " " + MSGResources[msgId], paras), ex);
        }

        /// <summary>
        /// 向指定文件写入日志信息
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <param name="msg">日志信息</param>
        /// <param name="ex">异常信息</param>
        private static void WriteLog(string filePath, string msg, Exception ex)
        {
            lock (SystemInfo)
            {
                StringBuilder log = new StringBuilder();
                log.AppendLine(string.Format("{0} {1}", DateTime.Now.ToString(FORMAT_LONG_DATETIME), msg));
                if (ex != null && SystemInfo.ExceptionOutput)
                {
                    log.AppendLine("-------------------------------------------------------------------");
                    log.AppendLine(ex.ToString());
                    log.AppendLine("-------------------------------------------------------------------");
                }
                try
                {
                    using (System.IO.StreamWriter sw = new System.IO.StreamWriter(filePath, true, Encoding.UTF8))
                    {
                        sw.Write(log.ToString());
                    }
                }
                catch
                {
                    try
                    {
                        using (System.IO.StreamWriter sw = new System.IO.StreamWriter(filePath + "_", true, Encoding.UTF8))
                        {
                            sw.Write(log.ToString());
                        }
                    }
                    catch { }
                }
            }
        }

        /// <summary>
        /// 获取操作错误日志路径
        /// </summary>
        /// <returns>返回路径</returns>
        private static string GetOperationLogPath()
        {
            return System.IO.Path.Combine(GlobalObject.LogFilePath, "OpErr_" + DateTime.Now.ToString(FORMAT_DATE) + ".txt");
        }

        /// <summary>
        /// 获取系统日志路径
        /// </summary>
        /// <returns>返回路径</returns>
        private static string GetSystemLogPath()
        {
            return System.IO.Path.Combine(GlobalObject.LogFilePath, "SysLog_" + DateTime.Now.ToString(FORMAT_MONTH) + ".txt");
        }


        #region 邮件唯一标识对象

        public class MailSignObject
        {
            /// <summary>
            /// 实例化
            /// </summary>
            public static MailSignObject Instance = new MailSignObject();

            /// <summary>
            /// 字符列表
            /// </summary>
            private static readonly char[] CODE_LIST = {
                '0','1','2','3','4','5','6','7','8','9',
                'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
                'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
                'U', 'V', 'W', 'X', 'Y', 'Z'
            };
            /// <summary>
            /// 参考时间
            /// </summary>
            private DateTime m_ReferenceTime;
            /// <summary>
            /// 参考时间内记录生成数
            /// </summary>
            private int m_RecordCount;

            /// <summary>
            /// 初始化
            /// </summary>
            public MailSignObject()
            {
                m_ReferenceTime = DateTime.Now;
                m_RecordCount = 0;
            }

            /// <summary>
            /// 生成邮件唯一标识
            /// </summary>
            /// <returns>返回唯一标识</returns>
            public string Generate()
            {
                lock (this)
                {
                    DateTime crtTime = DateTime.Now;
                    if (m_ReferenceTime.Second != crtTime.Second || m_ReferenceTime.Minute != crtTime.Minute || m_ReferenceTime.Hour != crtTime.Hour)
                    {
                        m_ReferenceTime = crtTime;
                        m_RecordCount = 1;
                    }
                    else
                    {
                        m_RecordCount++;
                        if (m_RecordCount > 839808)
                        {
                            m_RecordCount = 1;
                            m_ReferenceTime = m_ReferenceTime.AddSeconds(1);
                        }
                    }
                    long valueA = m_ReferenceTime.Second + m_ReferenceTime.Minute * 60 + m_ReferenceTime.Hour * 3600;
                    StringBuilder sign = new StringBuilder("          ");
                    sign[2] = CODE_LIST[m_ReferenceTime.Month];
                    sign[3] = CODE_LIST[m_ReferenceTime.Day];
                    sign[5] = CODE_LIST[valueA % 36];
                    valueA /= 36;
                    sign[9] = CODE_LIST[valueA % 36];
                    valueA /= 36;
                    sign[8] = CODE_LIST[valueA % 36];
                    valueA /= 36;
                    long valueB = m_RecordCount * 2 + valueA;
                    sign[4] = CODE_LIST[valueB % 36];
                    valueB /= 36;
                    sign[6] = CODE_LIST[valueB % 36];
                    valueB /= 36;
                    sign[7] = CODE_LIST[valueB % 36];
                    valueB /= 36;
                    if (m_RecordCount > 23328)
                    {
                        sign[0] = CODE_LIST[m_ReferenceTime.Year % 36];
                        sign[1] = CODE_LIST[valueB % 36];
                    }
                    else
                    {
                        sign[0] = CODE_LIST[(m_ReferenceTime.Year / 10) % 36];
                        sign[1] = CODE_LIST[m_ReferenceTime.Year % 10];
                    }
                    return sign.ToString();
                }
            }
        }

        #endregion

        /// <summary>
        /// 格式化短日期
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns></returns>
        public static string FormatShortDateTime(DateTime dateTime)
        {
            return dateTime.ToString(FORMAT_SHORT_DATETIME);
        }

        /// <summary>
        /// 格式化长日期
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns></returns>
        public static string FormatLongDateTime(DateTime dateTime)
        {
            return dateTime.ToString(FORMAT_LONG_DATETIME);
        }

        /// <summary>
        /// 格式化数据库日期
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns></returns>
        public static string FormatDBDate(DateTime dateTime)
        {
            return dateTime.ToString(FORMAT_DATE);
        }

        /// <summary>
        /// 格式化数据库时间
        /// </summary>
        /// <param name="dataTime"></param>
        /// <returns></returns>
        public static string FomratDBTime(DateTime dataTime)
        {
            return dataTime.ToString(FORMAT_TIME);
        }

    }
}
